import os
import re
import sys
import pandas as pd
import plotly.graph_objects as go
from datetime import datetime

def parse_txt_file(input_file):
    with open(input_file, 'r') as file:
        lines = file.readlines()
    
    timestamps = []
    mem_total = []
    mem_used = []
    mem_free = []
    cpu_total = []
    process_data = {}
    
    for line in lines:
        if line.startswith('Timestamp'):
            timestamp = line.split(': ')[1].strip()
            timestamps.append(timestamp)
        elif line.startswith('MEM[Total'):
            mem_info = re.findall(r"[\d\.\d]+", line)
            mem_total.append(float(mem_info[0]))
            mem_used.append(float(mem_info[1]))
            mem_free.append(float(mem_info[2]))
        elif line.startswith('CPU[Total'):
            cpu_info = re.findall(r"[\d\.\d]+", line)
            cpu_total.append(float(cpu_info[0]))
        else:
            match = re.match(r"(.+)\[Pid, cpu, mem\]: (\d+), ([\d\.]+) %, ([\d\.]+) MB", line)
            if match:
                process_name = match.group(1).strip().replace('\x00', '')
                pid = int(match.group(2))
                cpu = float(match.group(3))
                mem = float(match.group(4))
                if process_name not in process_data:
                    process_data[process_name] = {'cpu': [], 'mem': []}
                process_data[process_name]['cpu'].append(cpu)
                process_data[process_name]['mem'].append(mem)
    
    return timestamps, mem_total, mem_used, mem_free, cpu_total, process_data

def sanitize_filename(name, max_length=80):
    sanitized_name = re.sub(r'[^\w\-_\. ]', '_', name)
    return sanitized_name[:max_length]

def reduce_points(data, timestamps, threshold=10):
    reduced_data = []
    reduced_timestamps = []
    count = 0
    previous_value = None
    
    for i in range(len(data)):
        if data[i] != previous_value:
            count = 1
        else:
            count += 1
        
        if count == 1 or count % threshold == 0 or data[i] != previous_value:
            reduced_data.append(data[i])
            reduced_timestamps.append(timestamps[i])
        
        previous_value = data[i]
    
    return reduced_data, reduced_timestamps

def generate_plots(timestamps, mem_total, mem_used, mem_free, cpu_total, process_data, output_dir):
    timestamps = [datetime.strptime(ts, '%Y-%m-%d %H:%M:%S') for ts in timestamps]
    
    cpu_total, timestamps_cpu = reduce_points(cpu_total, timestamps)
    mem_total, timestamps_mem_total = reduce_points(mem_total, timestamps)
    mem_used, timestamps_mem_used = reduce_points(mem_used, timestamps)
    mem_free, timestamps_mem_free = reduce_points(mem_free, timestamps)
    
    fig_cpu = go.Figure()
    fig_cpu.add_trace(go.Scatter(x=timestamps_cpu, y=cpu_total, mode='lines+markers', name='Total CPU Usage (%)', line=dict(width=0.5), marker=dict(size=2)))
    fig_cpu.update_layout(title='CPU Usage Over Time',
                          xaxis_title='Timestamp',
                          yaxis_title='CPU Usage (%)',
                          xaxis_tickformat='%Y-%m-%d %H:%M:%S',
                          hovermode='x unified')
    fig_cpu.write_html(os.path.join(output_dir, 'cpu_usage_plot.html'))
    
    fig_mem = go.Figure()
    fig_mem.add_trace(go.Scatter(x=timestamps_mem_total, y=mem_total, mode='lines+markers', name='Total MEM (MB)', line=dict(width=0.5), marker=dict(size=2)))
    fig_mem.add_trace(go.Scatter(x=timestamps_mem_used, y=mem_used, mode='lines+markers', name='Used MEM (MB)', line=dict(width=0.5), marker=dict(size=2)))
    fig_mem.add_trace(go.Scatter(x=timestamps_mem_free, y=mem_free, mode='lines+markers', name='Free MEM (MB)', line=dict(width=0.5), marker=dict(size=2)))
    fig_mem.update_layout(title='Memory Usage Over Time',
                          xaxis_title='Timestamp',
                          yaxis_title='Memory (MB)',
                          xaxis_tickformat='%Y-%m-%d %H:%M:%S',
                          hovermode='x unified')
    fig_mem.write_html(os.path.join(output_dir, 'mem_usage_plot.html'))
    
    for process, metrics in process_data.items():
        sanitized_process_name = sanitize_filename(process)
        
        min_length = min(len(metrics['cpu']), len(timestamps))
        process_cpu = metrics['cpu'][:min_length]
        process_mem = metrics['mem'][:min_length]
        process_timestamps = timestamps[:min_length]

        process_cpu, timestamps_process_cpu = reduce_points(process_cpu, process_timestamps)
        process_mem, timestamps_process_mem = reduce_points(process_mem, process_timestamps)
        
        fig_process_cpu = go.Figure()
        fig_process_cpu.add_trace(go.Scatter(x=timestamps_process_cpu, y=process_cpu, mode='lines+markers', name=f'{process} CPU Usage (%)', line=dict(width=0.5, color='green'), marker=dict(size=2)))
        fig_process_cpu.update_layout(title=f'{process} CPU Usage Over Time',
                                      xaxis_title='Timestamp',
                                      yaxis_title='CPU Usage (%)',
                                      xaxis_tickformat='%Y-%m-%d %H:%M:%S',
                                      hovermode='x unified')
        fig_process_cpu.write_html(os.path.join(output_dir, f'{sanitized_process_name}_cpu_usage_plot.html'))

        fig_process_mem = go.Figure()
        fig_process_mem.add_trace(go.Scatter(x=timestamps_process_mem, y=process_mem, mode='lines+markers', name=f'{process} MEM Usage (MB)', line=dict(width=0.5, color='blue'), marker=dict(size=2)))
        fig_process_mem.update_layout(title=f'{process} MEM Usage Over Time',
                                      xaxis_title='Timestamp',
                                      yaxis_title='Memory Usage (MB)',
                                      xaxis_tickformat='%Y-%m-%d %H:%M:%S',
                                      hovermode='x unified')
        fig_process_mem.write_html(os.path.join(output_dir, f'{sanitized_process_name}_mem_usage_plot.html'))

def generate_html(output_file, process_data):
    output_dir = os.path.dirname(output_file)
    
    with open(output_file, 'w') as f:
        f.write('<html><head><title>System and Process Monitoring</title></head><body>')
        f.write('<div style="text-align:right; padding: 10px;">')
        f.write('<p>让中国智能车跑在全世界的马路上</p>')
        f.write('<p>数据来源：大卓</p>')
        f.write('</div>')
        
        f.write('<h1>System Monitoring</h1>')
        f.write('<iframe src="cpu_usage_plot.html" width="100%" height="500"></iframe>')
        f.write('<iframe src="mem_usage_plot.html" width="100%" height="500"></iframe>')
        
        f.write('<h1>Process Monitoring</h1>')
        for process in process_data.keys():
            process_safe_name = sanitize_filename(process)
            f.write(f'<h2>{process}</h2>')
            f.write(f'<iframe src="{process_safe_name}_cpu_usage_plot.html" width="100%" height="500"></iframe>')
            f.write(f'<iframe src="{process_safe_name}_mem_usage_plot.html" width="100%" height="500"></iframe>')
        
        f.write('</body></html>')

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Usage: python script.py <input_file> <output_file>")
        sys.exit(1)

    input_file = sys.argv[1]
    output_file = sys.argv[2]

    timestamps, mem_total, mem_used, mem_free, cpu_total, process_data = parse_txt_file(input_file)
    output_dir = os.path.dirname(output_file)
    generate_plots(timestamps, mem_total, mem_used, mem_free, cpu_total, process_data, output_dir)
    generate_html(output_file, process_data)

